/*
 * Config.java
 * The file read and parse the appconfig.xml configuration
 * appconfig.xml set the list of all the agents and what the agent can do
 * 
 * */


package wps.servicebus;

import java.io.IOException;
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Config {
	static Logger logger = Logger.getLogger(Config.class);
	public static String RootPath=".\\";
	public static String ConfigPath = RootPath + "config\\";
	public static String ConfigFilePath = ConfigPath + "appconfig.xml";
	
	private ArrayList<Application> applications = null;
	private ArrayList<Agent> agents = null;
	public Config() throws Exception{
		applications = new ArrayList<Application>();
		agents = new ArrayList<Agent>();
		parse();
	}
	public void parse(){
		DOMParser parser = new DOMParser();
		try {
			parser.parse(ConfigFilePath);
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Document doc = parser.getDocument();
		Element apps = getRootNode(doc, "applications");
		Element ags = getRootNode(doc, "agents");

		NodeList app_nodes = apps.getElementsByTagName("application");		
		for(int i = 0; i < app_nodes.getLength(); i++){
			Application app = new Application();
			set(app, (Element)app_nodes.item(i));
			applications.add(app);
		}
		
		NodeList agent_nodes = ags.getElementsByTagName("agent");
		for(int i = 0; i < agent_nodes.getLength(); i++){
			Agent agent = new Agent();
			set(agent, (Element)agent_nodes.item(i));
			agents.add(agent);
		}		
	}
	private Element getRootNode(Document doc, String qname) {
		Node root = doc.getElementsByTagName("appconfig").item(0);		
		NodeList nodes = root.getChildNodes();
		Element result = null;
		for(int i = 0; i < nodes.getLength(); i++){
//			logger.debug(nodes.item(i).getNodeName());
			if(nodes.item(i).getNodeName().equals(qname)){
				result = (Element)nodes.item(i);
			}
		}
		if(result == null){
			logger.error("There is no " + qname + " defined!");
		}
		return result;
	}
	private void set(Agent agent, Element item) {
		agent.setName(item.getAttribute("id"));
		agent.setAddr(getStringValue(item, "address"));
		agent.setPort(getIntValue(item, "port"));
		agent.setApplications(getStringArray(item));
		
	}
	private ArrayList<String> getStringArray(Element item) {
		NodeList nodes = item.getElementsByTagName("applications");
		if(nodes == null || nodes.getLength() == 0){
			return null;
		}else{
			Element e = (Element)nodes.item(0);
			nodes = e.getElementsByTagName("application");
			ArrayList<String> apps = new ArrayList<String>();
			for(int i = 0; i < nodes.getLength(); i++){
				apps.add(((Element)nodes.item(i)).getAttribute("id"));
			}
			return apps;
		}
	}
	private int getIntValue(Element item, String name) {
		return Integer.parseInt(getStringValue(item, name));
	}
	private String getStringValue(Element item, String name) {
		NodeList nodes = item.getElementsByTagName(name);
		if(nodes.getLength() != 1){
			return null;
		}else{
			Element e = (Element)nodes.item(0);
			return e.getFirstChild().getNodeValue();
		}
	}
	private void set(Application app, Element item) {		
		app.setName(item.getAttribute("id"));
		app.setDescription(item.getElementsByTagName("description").item(0).getChildNodes().item(0).getNodeValue());
		app.setDefault(item.getAttribute("default").equals("true") ? true : false);		
	}
	public static void main(String[] args) throws Exception{
		Config config = new Config();
		config.print();
	}
	private void print() {
		for(Application app : this.applications){
			logger.debug(app.getName());
			logger.debug(app.getDescription());
			logger.debug(app.isDefault());
		}
		for(Agent agent : this.agents){
			logger.debug(agent.getName());
			logger.debug(agent.getAddr());
			logger.debug(agent.getPort());
			for(String app : agent.getApplications()){
				logger.debug(app);
			}
		}
		
	}

	public ArrayList<Application> getApplications() {
		return applications;
	}

	public ArrayList<Agent> getAgents() {
		return agents;
	}
	
	public class Application{
		private String name;
		private String description;
		private boolean isDefault;
		public Application(String name, String description, boolean isDefault){
			this.setName(name);
			this.setDescription(description);
			this.setDefault(isDefault);
		}
		public Application(){}
		public void setName(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		public void setDescription(String description) {
			this.description = description;
		}
		public String getDescription() {
			return description;
		}
		public void setDefault(boolean isDefault) {
			this.isDefault = isDefault;
		}
		public boolean isDefault() {
			return isDefault;
		}
	}
	
	public class Agent{		
		private String name;
		private String addr;
		private int port;
		private ArrayList<String> applications = null;
		public Agent(){
			this.applications = new ArrayList<String>();
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		public void setAddr(String addr) {
			this.addr = addr;
		}
		public String getAddr() {
			return addr;
		}
		public void setPort(int port) {
			this.port = port;
		}
		public int getPort() {
			return port;
		}
		public void setApplications(ArrayList<String> applications) {
//			logger.debug(applications.size());
//			logger.debug(this.applications == null);
			this.applications.addAll(applications);		
		}
		public ArrayList<String> getApplications() {
			return applications;
		}	
	}
	
}
